import java.io.File;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.lang.reflect.Type;
import java.util.*;
import java.util.stream.Stream;

public class GenerateClassInfo {
	private static final Set<String> filterMethodNameList = new HashSet<>();

	static {
		// 过滤掉不需要打印的方法
		filterMethodNameList.add("equals");
		filterMethodNameList.add("toString");
		filterMethodNameList.add("hashCode");
	}

	public static void main(String[] args) {
		System.out.print("类所在目录：");
		Scanner scanner = new Scanner(System.in);

		String dirPath = scanner.nextLine();
		File dir = new File(dirPath);
		String[] filenames = dir.list((dir1, name) -> name.endsWith(".java"));
		String prefix = getPackageName(dir);

		List<Class<?>> list = Stream.of(filenames)
				.map(s -> s.substring(0, s.length() - 5))
				.map(className -> {
					try {
						return Class.forName(prefix + "." + className);
					} catch (ClassNotFoundException e) {
						e.printStackTrace();
					}
					return Object.class;
				})
				.filter(aClass -> aClass != Objects.class)
				.toList();
		printClassInfo(list);
	}

	private static String getPackageName(File dir) {
		String dirPath = dir.getAbsolutePath();
		String root = "\\java\\";
		return dir.getAbsolutePath().substring(dirPath.indexOf(root) + root.length()).replaceAll("\\\\", ".");
	}

	private static void printClassInfo(List<Class<?>> list) {
		StringBuilder b = new StringBuilder();
		for (Class<?> c : list) {
			b.append(c.getSimpleName()).append("\n\n");
			// 属性
			for (Field field : c.getDeclaredFields()) {
				// 泛型类型
				String genericType = "";
				if (field.getType() == List.class || field.getType() == Set.class) {
					genericType = getGenericString(field.getGenericType());
				}
				b.append("+ ").append(field.getName()).append(": ").append(field.getType().getSimpleName());
				if (!genericType.equals("")) b.append("<").append(genericType).append(">");
				b.append("\n");
			}
			b.append("\n");

			// 方法
			for (Method method : c.getDeclaredMethods()) {
				if (filterMethodNameList.contains(method.getName())) continue;

				b.append("+ ").append(method.getName()).append("(");

				// 参数
				Parameter[] parameters = method.getParameters();
				if (parameters != null && parameters.length != 0) {
					for (Parameter parameter : parameters) {
						b.append(parameter.getType().getSimpleName());
						if (parameter.getType() == List.class || parameter.getType() == Set.class) {
							b.append("<").append(getGenericString(parameter.getParameterizedType())).append(">");
						}

						b.append(" ").append(parameter.getName()).append(", ");
					}
					b.delete(b.length() - 2, b.length());
				}

				// 返回值
				String genericType = "";
				if (method.getReturnType() == List.class || method.getReturnType() == Set.class) {
					genericType = getGenericString(method.getGenericReturnType());
				}
				b.append(")").append(": ").append(method.getReturnType().getSimpleName());
				if (!genericType.equals("")) b.append("<").append(genericType).append(">");
				b.append("\n");
			}
			b.append("------------------------------------------\n");

		}

		System.out.println(b);
	}

	/**
	 * 泛型类型
	 */
	private static String getGenericString(Type type) {
		String genericType = type.getTypeName();
		return genericType.substring(genericType.lastIndexOf(".") + 1, genericType.length() - 1);
	}
}
